home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Libris Britannia 4
/
science library(b).zip
/
science library(b)
/
UTILITIE
/
UNIX_COH
/
2772.ZIP
/
CUT.SHZ
/
CUT
/
cut.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-07-02
|
5KB
|
254 lines
/*
* This acts the same as SV cut(1), except that the list of numbers
* does not have to be assending.
*
* John Weald
*/
#include <stdio.h>
#include <ctype.h>
#define MAXLINE 1024 /* The max. length of a line */
extern void exit();
main(argc, argv)
int argc;
char *argv[];
{
extern char *optarg;
extern int optind;
static int fields[MAXLINE];/* The field markers. True if this field */
/* is to be cut, False otherwise */
FILE *fp; /* All the input files or stdin */
char buf[MAXLINE]; /* The input buffer */
int c; /* The command line option */
int err = 0; /* True if error in command line */
int fflag = 0; /* True if -f on command line */
int cflag = 0; /* True if -c on command line */
int suppress = 0; /* Suppress lines with no delimitor */
char fs = '\t'; /* The field separator */
while ((c = getopt(argc, argv, "f:d:c:s")) != EOF)
{
switch (c)
{
case 'f':
/* By Field */
list(fields, optarg);
fflag++;
if (cflag)
err++;
break;
case 'c':
/* By character */
list(fields, optarg);
/* Implied suppress */
suppress++;
cflag++;
if (fflag)
err++;
break;
case 'd':
/* A new field spererator */
fs = *optarg;
break;
case 's':
suppress++;
break;
default:
prusage();
}
}
if (!cflag && !fflag)
{
fprintf(stderr, "Must have one of -f or -c\n");
err++;
}
if (err)
prusage();
/*
* Loop on all the files.
*/
do {
if (optind == argc)
fp = stdin;
else if ((fp = fopen(argv[optind], "r")) == (FILE *)NULL)
{
fprintf(stderr, "Failed to open file %s\n",
argv[optind]);
exit(1);
}
/*
* Loop on all lines in the file.
*/
while (fgets(buf, sizeof(buf), fp) != (char *)NULL)
{
cut(buf, fields, fs, suppress, cflag);
}
(void)fclose(fp);
} while (++optind < argc);
exit(0);
/* NOTREACHED */
}
/*
* Cut the line. This handles both character and field cutting.
* For character cutting the f array gives character positions, for
* fields it gives the field number. It must be indexed by either the
* character number or the field number.
*/
cut(in, f, fs, sup, c_or_f)
register char *in; /* The input line */
int f[]; /* The field cutting flags */
char fs; /* The field seperator */
int sup; /* Suppress lines with no-delimitor? */
int c_or_f; /* Cut by char. (true), or field (false)*/
{
char obuf[MAXLINE]; /* Output buffer */
register char *optr = obuf;
register int i; /* Character count */
register int fld; /* The field count */
char *instart = in; /* To print lines with no delimiters */
for (fld = 0, i = 0; i < MAXLINE; i++)
{
if (*in == '\n')
{
/* End of the line */
*optr = '\0';
/* Any thing to cut? */
if (optr != obuf)
{
/* Get ride of trailing seperator */
if (*(optr - 1) == fs)
*(optr - 1) = '\0';
puts(obuf);
}
else if (!sup)
printf(instart);
return;
}
if (f[c_or_f ? i : fld])
{
*optr++ = *in;
}
/* End of field? */
if (*in++ == fs)
fld++;
}
fprintf(stderr, "Line too long, maximum length is %d\n", MAXLINE);
exit(1);
}
/*
* Parse the list argument. The format is:
* n,n
* where n is either a number or a range of numbers in the format
* m-l
* m or l may be absent, indicating the start or end of the lines respectivly.
* Numbers must be in increasing order for m-l format, but not for n,n.
* Field numbers start at 1, but index into fields array starts at 0.
*
*/
list(f, l)
int f[]; /* The fields */
char *l; /* The list */
{
int range = 0; /* True if m-l format */
int low, high; /* the low and high numbers in a m-l pair*/
int i;
low = high = 0;
while (1)
{
switch(*l)
{
case '\0':
/* Is it m-<nothing>EOL? */
if (range)
{
/* Select rest of fields */
for(i = low - 1; i < MAXLINE; i++)
f[i]++;
}
else
f[low-1]++;
return;
case ',':
l++;
if (!range)
f[low-1]++;
range = 0;
low = 1;
break;
case '-':
l++;
range++;
/* Is it m-<nothing> */
if (isdigit((int)*l))
{
high = atoi(l);
/* Skip the digits */
while (isdigit((int) *l))
l++;
}
else
high = MAXLINE;
/* Is the range the correct way around? */
if (low > high)
{
fprintf(stderr, "Bad c/f list: %d > %d\n",
low, high);
exit(1);
}
/* Set the field flags for the range */
for(i = low - 1; i < high; i++)
f[i]++;
break;
default:
/* either a number or an error */
if (!isdigit((int) *l))
{
fprintf(stderr, "Bad c/f list at %s\n", l);
exit(1);
}
low = atoi(l);
if (low == 0)
{
fprintf(stderr, "Fields start at 1 not 0\n");
exit(1);
}
/* Skip the digits */
while (isdigit((int) *l))
l++;
break;
}
}
}
prusage()
{
fprintf(stderr, "cut [-d<delimitor>] [-s] -c<list>|-f<list> [files]\n");
exit(1);
}